from random import shuffle
from FrenchDeck import FrenchDeck
from collections import abc


# 接口：从协议到抽象基类
# 1、Python文化中的接口和协议
# 2、Python喜欢序列
class Foo:
    # 只实现序列协议的一部分，这样足够访问元素、迭代和使用 in 运算符了
    def __getitem__(self, pos):
        return range(0, 30, 10)[pos]


f = Foo()
print(f[1])
for i in f:
    print(i)
print(20 in f)
print(15 in f)
# 3、使用猴子补丁在运行时实现协议
l = list(range(10))
shuffle(l)
print(l)
# FrenckDeck无法打乱
deck = FrenchDeck()


# shuffle(deck)
# 'FrenchDeck' object does not support item assignment
# FrenchDeck只实现了不可变的序列协议，可变的序列还需要提供__setitem__方法
def set_card(de, position, card):
    de._cards[position] = card


# 猴子补丁  在运行时修改类
FrenchDeck.__setitem__ = set_card
shuffle(deck)
print(deck[:5])


# 4、Alex Martelli的水禽
# 抽象基类的本质就是几个特殊方法
class Struggle:

    def __len__(self):
        return 23


print(isinstance(Struggle(), abc.Sized))

# 5、定义抽象基类的子类 @see FrenchDeck2.py

# 6、标准库中的抽象基类 @since 2.6
# collections.abc模块中的抽象基类
# https://docs.python.org/3/library/collections.abc.html#collections-abstract-base-classes
# 抽象基类的数字塔 numbers包
# https://docs.python.org/3/library/numbers.html
# 7、定义并使用一个抽象基类
# @see tombola.py bingo.py lotto.py tombolist.py
# 8、Tombola子类的测试方法
# __subclasses__() 返回类的直接子类，不含虚拟子类
# _abc_registry 只有抽象基类有这个属性，WeakSet对象，即抽象类注册的虚拟子类的弱引用(3.7之后没有)
# 9、Python使用register的方式
# Tombola.register(TomboList)
# 10、鹅的行为有可能像鸭子
# 即便不注册，抽象基类也能把一个类识别为虚拟子类
# 这是因为 abc.Sized 实现了一个特殊的类方法，名为 __subclasshook__
print(isinstance(Struggle(),abc.Sized))
print(issubclass(Struggle,abc.Sized))

